#include "ustc_comdef.h"
#include "ustc_hif.h"
#include "ustc_api.h"
#include "ustc_cmr_drv.h"


#define RATE_ACCURACY	100L
#define COL_PIXEL_ALIGNMENT 	3


USTC_U32 ustc_camera_init_hw(USTC_CAMERA_T *pCamera, USTC_U16 width, USTC_U16 height, USTC_U16 count)
{
	USTC_U32 tmp;

	pCamera->wFrameCount=count;
	pCamera->wImageSize=width*height;
	tmp=pCamera->wImageSize*count;
	if (count>1)
		pCamera->wBufSize=(tmp+USTC_CMIF_FIFO_SIZE)&(~(USTC_CMIF_FIFO_SIZE-1));
	else
		pCamera->wBufSize=tmp;


	return pCamera->wBufSize;
}


void ustc_camera_init_sw(USTC_CAMERA_T *pCamera, USTC_U16 *buf, USTC_U32 blankCnt)
{
	pCamera->wDataCnt=0;
	pCamera->wMark=(pCamera->wImageSize*2)&(~(USTC_CMIF_FIFO_SIZE-1));
	pCamera->wBlankFrame=blankCnt;
	pCamera->pData=buf;
	pCamera->pDisp=buf;
	pCamera->pStart=buf;
	pCamera->pEnd=buf+pCamera->wBufSize;
	if (FRAME_BUFFER_COUNT>1)
	{
		pCamera->pDisp-=pCamera->wImageSize;
		if (blankCnt<1)
			pCamera->wBlankFrame=1;//discard the first one frame
	}
}

void ustc_camera_open(USTC_CAMERA_T *pCamera)
{
	/* set sensor interface */
	USTC_IO_OUTW(CMR_SEN_IF_SEL, 0);
	
	USTC_IO_OUTW(CMR_SEN_SIGNAL_SEL,pCamera->clk_cfg);

	USTC_IO_OUTW(CMR_SEN_CCIR656_SEL,pCamera->wFrameSync);

	USTC_IO_OUTW(CMR_DMA_REQ_MSK, CMR_IF_DMA_NORMAL);

//	if (FRAME_BUFFER_COUNT<2)
		USTC_IO_OUTW(CMR_INT_MASK, CMR_INT_MASK_FRAME_DONE);
//	else
//		USTC_IO_OUTW(CMR_INT_MASK, 0);
	
	USTC_IO_OUTW(CMR_INT_STATU,0x3F);

	if (0)//<pCamera->ccir656_enable)
	{
		USTC_IO_OUTW(CMR_SEN_IF_SEL,CMR_SEN_IF_SEL_SENSOR_IF_ENANLE|CMR_SEN_IF_SEL_SENSOR_CCIR656_ENANLE); 
	}
	else
	{
		USTC_IO_OUTW(CMR_SEN_IF_SEL, CMR_SEN_IF_SEL_SENSOR_IF_ENANLE);
	}
}

static void ustc_camera_fit_mode(RESIZER_T *resizer, USTC_U8 fit_mode, USTC_U8 deformation)
{
	USTC_U32 t_w;
	USTC_U32 r_x=1, r_y=0;

	t_w = (resizer->t_w+COL_PIXEL_ALIGNMENT)&(~COL_PIXEL_ALIGNMENT);

	if (t_w > resizer->w_w)
	{//target width larger than window width
		resizer->t_w = resizer->w_w;
		t_w 		 = (resizer->t_w+COL_PIXEL_ALIGNMENT)&(~COL_PIXEL_ALIGNMENT);
		resizer->w_w = t_w;
	}
	if (resizer->t_h > resizer->w_h)
	{//target height larger than window height
		resizer->t_h = resizer->w_h;
	}

	if (deformation)
	{//allow deformation of image
		r_x = resizer->w_w/t_w;
		r_y = resizer->w_h/resizer->t_h;
	}
	
	if (r_x!=r_y)
	{//reduce deformation of image
		r_x = (RATE_ACCURACY*(USTC_U32)resizer->w_w/t_w);
		r_y = (RATE_ACCURACY*(USTC_U32)resizer->w_h/resizer->t_h);
	}

	if (r_x < r_y)
	{//reduce target width
		resizer->t_w = ( ((USTC_U32)resizer->w_w*RATE_ACCURACY/r_y) );
		t_w 		 = (resizer->t_w+COL_PIXEL_ALIGNMENT) & (~COL_PIXEL_ALIGNMENT);
		r_x 		 = ( RATE_ACCURACY*(USTC_U32)resizer->w_w/t_w );

		if (r_x/100 < r_y/100) {
			resizer->t_w&=~COL_PIXEL_ALIGNMENT;
			t_w 		 = resizer->t_w;
			r_x 		 =(RATE_ACCURACY*(USTC_U32)resizer->w_w/t_w );
		}

		while (r_y/100 < r_x/100) {
			resizer->t_h--;
			r_y = (RATE_ACCURACY*(USTC_U32)resizer->w_h/resizer->t_h);
		}
	}else if (r_x > r_y)
	{//reduce target height
		resizer->t_h = ( (USTC_U32)resizer->w_h*RATE_ACCURACY/r_x );
		while (r_y/100 > r_x/100) {
			resizer->t_h++;
			r_y = (RATE_ACCURACY*(USTC_U32)resizer->w_h/resizer->t_h);
		}
	}
	
	resizer->x	&=~1;
	resizer->w_w&=~1;
}

void ustc_camera_scale(USTC_CAMERA_T *pCamera, RESIZER_T *p_resizer)
{
	ustc_camera_fit_mode(p_resizer, pCamera->wFitMode, 0);
	ustc_cmif_scale(p_resizer, pCamera->wSensorSize);
}

void ustc_camera_reset(USTC_CAMERA_T *pCamera)
{
	USTC_U32 sys_ctrl;
	USTC_U32 reset;
	
	reset=ustc_inh(HIF_SYS_SW_RST);
	ustc_outh(HIF_SYS_SW_RST, reset|HIF_RST_CMIF_LOGIC);

	sys_ctrl=ustc_inh(HIF_SYS_CTRL);
	ustc_outh(HIF_SYS_CTRL,sys_ctrl|0x220);
	ustc_outh(HIF_SYS_CTRL,sys_ctrl);

	if (FRAME_BUFFER_COUNT>1)
	{
		pCamera->pData=pCamera->pStart;
		pCamera->pDisp=pCamera->pStart-pCamera->wImageSize;
		pCamera->wDataCnt=0;
	}
	
	ustc_outh(HIF_SYS_SW_RST, reset);
}
